package com.telit.firecommand.controller;

import com.telit.common.constant.Constant;
import com.telit.common.entity.DataReturn;
import com.telit.common.enums.ResultCode;
import com.telit.firecommand.model.camera.QueryDevicesRequest;
import com.telit.firecommand.service.CameraMonitorService;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiImplicitParam;
import io.swagger.annotations.ApiImplicitParams;
import io.swagger.annotations.ApiOperation;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.MediaType;
import org.springframework.web.bind.annotation.*;

import javax.servlet.http.HttpServletResponse;
import java.util.List;
import java.util.Map;


/**
 * 视频监控操作API
 *
 * @author yuezhuang
 * @date 2022-08-30
 */
@Slf4j
@RestController
@RequestMapping(value = "/camera-monitor", produces = MediaType.APPLICATION_JSON_VALUE)
@Api(tags = "视频监控操作API", value = "视频监控操作API", produces = MediaType.APPLICATION_JSON_VALUE)
public class CameraMonitorController {

    @Autowired
    private CameraMonitorService cameraMonitorService;

    /**
     * 获取监控点预览取流flv URL
     *
     * @param cameraIndexCode 监控点编号
     * @param beginTime       开始时间
     * @param endTime         结束时间
     * @param protocol        结束时间
     *
     * @return DataReturn
     */
    @GetMapping(value = "/playbackURLs", produces = MediaType.APPLICATION_JSON_VALUE)
    @ApiImplicitParams({
            @ApiImplicitParam(name = "cameraIndexCode", value = "监控点唯一标识", required = true, paramType = "query", dataType = "String"),
            @ApiImplicitParam(name = "beginTime", value = "开始时间，格式 yyyy-MM-dd HH:mm:ss", required = true, paramType = "query", dataType = "String"),
            @ApiImplicitParam(name = "endTime", value = "结束时间，格式 yyyy-MM-dd HH:mm:ss", required = true, paramType = "query", dataType = "String"),
            @ApiImplicitParam(name = "protocol", value = "固定值：httpsflv", required = true, paramType = "query", dataType = "String"),
            @ApiImplicitParam(name = "recordLocation", value = "录像存储位置（0-中心存储，1-设备存储）,默认中心存储", paramType = "query", dataType = "String"),
    })
    @ApiOperation(value = "获取监控点回放取流URL", httpMethod = Constant.REQUEST_METHOD_GET)
    public DataReturn playbackURLs(@RequestParam String cameraIndexCode,
                                   @RequestParam String beginTime,
                                   @RequestParam String endTime,
                                   @RequestParam String protocol,
                                   @RequestParam(value = "recordLocation", required = false) String recordLocation) {
        return DataReturn.ok(
                cameraMonitorService.playbackURLs(cameraIndexCode, beginTime, endTime, protocol, recordLocation));
    }

    @ApiImplicitParams({
            @ApiImplicitParam(name = "indexCode", value = "监控唯一标识", required = true, paramType = "query", dataType = "String"),
    })
    @GetMapping(value = "/query-rtsp-url")
    @ApiOperation(value = "根据监控名查询实时视频流", httpMethod = Constant.REQUEST_METHOD_GET)
    public DataReturn queryRtspUrl(@RequestParam(value = "indexCode") String indexCode) {
        return DataReturn.ok(cameraMonitorService.queryRtspUrl(indexCode));
    }

    @GetMapping(value = "/query-flv-url")
    @ApiOperation(value = "根据监控名查询实时视频流", httpMethod = Constant.REQUEST_METHOD_GET)
    public DataReturn queryFlvpUrl(@RequestParam(value = "indexCode") String indexCode) {
//        String previewUrl = RedisUtils.get(RedisKeyConstant.CAMERA_PREVIEW_URL + indexCode);
//        if (StringUtils.isEmpty(previewUrl)) {
//            previewUrl = cameraMonitorService.queryFlvpUrl(indexCode);
//        }
        return DataReturn.ok(cameraMonitorService.queryFlvpUrl(indexCode));
    }

    @GetMapping(value = "/query-devices")
    @ApiOperation(value = "查询设备信息", httpMethod = Constant.REQUEST_METHOD_GET)
    public DataReturn<List<Map>> queryDevices(QueryDevicesRequest queryDevicesRequest) {
        return DataReturn.ok(cameraMonitorService.queryDevices(queryDevicesRequest));
    }

    @ApiImplicitParams({
            @ApiImplicitParam(name = "user", value = "user", required = true, paramType = "query", dataType = "String"),
            @ApiImplicitParam(name = "password", value = "password", required = true, paramType = "query", dataType = "String"),
    })
    @GetMapping(value = "/h5-login")
    @ApiOperation(value = "h5登录接口", httpMethod = Constant.REQUEST_METHOD_GET)
    public DataReturn h5Login(@RequestParam(value = "user") String user,
                              @RequestParam(value = "password") String password) {
        return DataReturn.ok(cameraMonitorService.h5Login(user, password));
    }

    @ApiImplicitParams({
            @ApiImplicitParam(name = "session", value = "session", required = true, paramType = "query", dataType = "String"),
    })
    @GetMapping(value = "/h5-keep-alive")
    @ApiOperation(value = "h5保活接口", httpMethod = Constant.REQUEST_METHOD_GET)
    public DataReturn h5KeepAlive(@RequestParam(value = "session") String session) {
        try {
            return DataReturn.ok(cameraMonitorService.h5KeepAlive(session));
        } catch (Exception e) {
            log.warn("H5保活异常:{}", e.getMessage());
            return DataReturn.failure(ResultCode.AUTHC_ILLEGAL);
        }
    }

    @ApiImplicitParams({
            @ApiImplicitParam(name = "token", value = "token", required = true, paramType = "query", dataType = "String"),
            @ApiImplicitParam(name = "action", value = "action", required = true, paramType = "query", dataType = "String"),
            @ApiImplicitParam(name = "speed", value = "speed", required = true, paramType = "query", dataType = "String"),
            @ApiImplicitParam(name = "session", value = "session", required = true, paramType = "query", dataType = "String"),
    })
    @PostMapping(value = "/ptz-ctl")
    @ApiOperation(value = "h5云台控制", httpMethod = Constant.REQUEST_METHOD_POST)
    public DataReturn ptzCtl(@RequestParam(value = "token") String token,
                             @RequestParam(value = "action") String action,
                             @RequestParam(value = "speed") String speed,
                             @RequestParam(value = "session") String session) {
        return DataReturn.ok(cameraMonitorService.ptzCtl(token, action, speed, session));
    }

    @ApiImplicitParams({
            @ApiImplicitParam(name = "cameraId", value = "cameraId", paramType = "query", dataType = "String"),
            @ApiImplicitParam(name = "indexCode", value = "indexCode", required = true, paramType = "query", dataType = "String"),
            @ApiImplicitParam(name = "presetName", value = "预置点名称", required = true, paramType = "query", dataType = "String"),
            @ApiImplicitParam(name = "presetIndex", value = "巡航组索引（默认 0）", paramType = "query", dataType = "String"),
            @ApiImplicitParam(name = "standTime", value = "停留时间：15-30，默认 15", paramType = "query", dataType = "String"),
            @ApiImplicitParam(name = "speed", value = "跳转速度 1-10，默认 7", paramType = "query", dataType = "String"),
    })
    @PostMapping(value = "/set-presets")
    @ApiOperation(value = "设置预置点", httpMethod = Constant.REQUEST_METHOD_POST)
    public DataReturn setPresets(@RequestParam(value = "cameraId", required = false) Long cameraId,
                                 @RequestParam(value = "indexCode") String indexCode,
                                 @RequestParam(value = "presetName") String presetName,
                                 @RequestParam(value = "presetIndex", required = false, defaultValue = "0") Integer presetIndex,
                                 @RequestParam(value = "standTime", required = false, defaultValue = "15") Integer standTime,
                                 @RequestParam(value = "speed", required = false, defaultValue = "7") Integer speed) {
        return DataReturn.ok(
                cameraMonitorService.setPresets(cameraId, indexCode, presetName, presetIndex, standTime, speed));
    }

    @ApiImplicitParams({
            @ApiImplicitParam(name = "cameraId", value = "cameraId", paramType = "query", dataType = "String"),
            @ApiImplicitParam(name = "indexCode", value = "indexCode", required = true, paramType = "query", dataType = "String"),
            @ApiImplicitParam(name = "presetIndex", value = "巡航组索引（默认 0）", paramType = "query", dataType = "String"),
            @ApiImplicitParam(name = "id", value = "预置点id", required = true, paramType = "query", dataType = "String"),
    })
    @PostMapping(value = "/del-presets")
    @ApiOperation(value = "删除预置点（删除巡航路线预置点）", httpMethod = Constant.REQUEST_METHOD_POST)
    public DataReturn delPresets(@RequestParam(value = "cameraId", required = false) Long cameraId,
                                 @RequestParam(value = "indexCode") String indexCode,
                                 @RequestParam(value = "presetIndex", required = false, defaultValue = "0") Integer presetIndex,
                                 @RequestParam(value = "id") Long id) {
        return DataReturn.ok(cameraMonitorService.delPresets(cameraId, indexCode, presetIndex, id));
    }

    @ApiImplicitParams({
            @ApiImplicitParam(name = "cameraId", value = "cameraId", paramType = "query", dataType = "String"),
            @ApiImplicitParam(name = "indexCode", value = "indexCode", required = true, paramType = "query", dataType = "String"),
    })
    @PostMapping(value = "/del-all-presets")
    @ApiOperation(value = "清除预置点（删除巡航路所有线预置点）", httpMethod = Constant.REQUEST_METHOD_POST)
    public DataReturn delAllPresets(@RequestParam(value = "cameraId", required = false) Long cameraId,
                                    @RequestParam(value = "indexCode") String indexCode) {
        cameraMonitorService.delAllPresets(cameraId, indexCode);
        return DataReturn.ok();
    }

    @ApiImplicitParams({
            @ApiImplicitParam(name = "cameraId", value = "cameraId", paramType = "query", dataType = "String"),
            @ApiImplicitParam(name = "indexCode", value = "indexCode", required = true, paramType = "query", dataType = "String"),
            @ApiImplicitParam(name = "presetIndex", value = "巡航组索引（默认 0）", paramType = "query", dataType = "String"),
            @ApiImplicitParam(name = "id", value = "预置点id", paramType = "query", dataType = "String"),
            @ApiImplicitParam(name = "standTime", value = "停留时间：15-30，默认 15", paramType = "query", dataType = "String"),
            @ApiImplicitParam(name = "speed", value = "跳转速度 1-10，默认 7", paramType = "query", dataType = "String"),
    })
    @PostMapping(value = "/set-to-cruise")
    @ApiOperation(value = "将预置点添加到巡航路线中", httpMethod = Constant.REQUEST_METHOD_POST)
    public DataReturn setToCruise(@RequestParam(value = "cameraId", required = false) Long cameraId,
                                  @RequestParam(value = "indexCode") String indexCode,
                                  @RequestParam(value = "presetIndex", required = false, defaultValue = "0") Integer presetIndex,
                                  @RequestParam(value = "id") Long id,
                                  @RequestParam(value = "standTime", required = false, defaultValue = "15") Integer standTime,
                                  @RequestParam(value = "speed", required = false, defaultValue = "7") Integer speed) {
        cameraMonitorService.setToCruise(cameraId, indexCode, presetIndex, id, standTime, speed);
        return DataReturn.ok();
    }

    @ApiImplicitParams({
            @ApiImplicitParam(name = "cameraId", value = "cameraId", paramType = "query", dataType = "String"),
            @ApiImplicitParam(name = "indexCode", value = "indexCode", required = true, paramType = "query", dataType = "String"),
    })
    @GetMapping(value = "/search-presets")
    @ApiOperation(value = "查询预置点", httpMethod = Constant.REQUEST_METHOD_GET)
    public DataReturn searchPresets(@RequestParam(value = "cameraId", required = false) Long cameraId,
                                    @RequestParam(value = "indexCode") String indexCode) {
        return DataReturn.ok(cameraMonitorService.searchPresets(cameraId, indexCode));
    }

    @ApiImplicitParams({
            @ApiImplicitParam(name = "indexCode", value = "indexCode", required = true, paramType = "query", dataType = "String"),
            @ApiImplicitParam(name = "presetIndex", value = "presetIndex", required = true, paramType = "query", dataType = "String"),
    })
    @PostMapping(value = "/go-to-presets")
    @ApiOperation(value = "移动到预置点", httpMethod = Constant.REQUEST_METHOD_POST)
    public DataReturn goToPresets(@RequestParam(value = "indexCode") String indexCode,
                                  @RequestParam(value = "presetIndex") Integer presetIndex) {
        return DataReturn.ok(cameraMonitorService.goToPresets(indexCode, presetIndex));
    }

    @ApiImplicitParams({
            @ApiImplicitParam(name = "indexCode", value = "监控点唯一标识，分页获取监控点资源接口获取返回参数cameraIndexCode", required = true, paramType = "query", dataType = "String"),
            @ApiImplicitParam(name = "action", value = "0-开始 "
                    + "1-停止 "
                    + "注：GOTO_PRESET命令下填任意值均可转到预置点,建议填0即可", required = true, paramType = "query", dataType = "String"),
            @ApiImplicitParam(name = "command", value = "不区分大小写 "
                    + "说明： "
                    + "LEFT 左转 "
                    + "RIGHT右转 "
                    + "UP 上转 "
                    + "DOWN 下转 "
                    + "ZOOM_IN 焦距变大 "
                    + "ZOOM_OUT 焦距变小 "
                    + "LEFT_UP 左上 "
                    + "LEFT_DOWN 左下 "
                    + "RIGHT_UP 右上 "
                    + "RIGHT_DOWN 右下 FOCUS_NEAR 焦点前移 "
                    + "FOCUS_FAR 焦点后移 IRIS_ENLARGE 光圈扩大 "
                    + "IRIS_REDUCE 光圈缩小 "
                    + "WIPER_SWITCH 接通雨刷开关 "
                    + "START_RECORD_TRACK开始记录轨迹 "
                    + "STOP_RECORD_TRACK 停止记录轨迹 "
                    + "START_TRACK 开始轨迹 "
                    + "STOP_TRACK 停止轨迹 "
                    + " "
                    + "以下命令presetIndex不可 "
                    + "为空： "
                    + "GOTO_PRESET到预置点", required = true, paramType = "query", dataType = "String"),
            @ApiImplicitParam(name = "speed", value = "云台速度，取值范围为1-100，默认50", paramType = "query", dataType = "String"),
            @ApiImplicitParam(name = "presetIndex", value = "预置点编号，整数，通常在300以内", paramType = "query", dataType = "String"),
            @ApiImplicitParam(name = "cruiseIndex", value = "自动巡航控制时有效", paramType = "query", dataType = "String"),
    })
    @PostMapping(value = "/ptz-control")
    @ApiOperation(value = "云台操作", httpMethod = Constant.REQUEST_METHOD_POST)
    public DataReturn ptzControl(@RequestParam(value = "indexCode") String indexCode,
                                 @RequestParam(value = "action") Integer action,
                                 @RequestParam(value = "command") String command,
                                 @RequestParam(value = "speed", required = false) Integer speed,
                                 @RequestParam(value = "presetIndex", required = false) Integer presetIndex,
                                 @RequestParam(value = "cruiseIndex", required = false) Integer cruiseIndex) {
        return DataReturn.ok(
                cameraMonitorService.ptzControl(indexCode, action, command, speed, presetIndex, cruiseIndex));
    }

//    @ApiImplicitParams({
//            @ApiImplicitParam(name = "indexCode", value = "indexCode", required = true, paramType = "query", dataType = "String"),
//            @ApiImplicitParam(name = "nameLike", value = "nameLike", paramType = "query", dataType = "String"),
//    })
//    @GetMapping(value = "/search-routes")
//    @ApiOperation(value = "查询巡航路线", httpMethod = Constant.REQUEST_METHOD_GET)
//    public DataReturn searchRoutes(@RequestParam(value = "indexCode") String indexCode,
//                                   @RequestParam(value = "nameLike", required = false) String nameLike) {
//        return DataReturn.ok(cameraMonitorService.searchRoutes(indexCode, nameLike));
//    }
//
//    @ApiImplicitParams({
//            @ApiImplicitParam(name = "cruiseRoutes", value = "cruiseRoutes", required = true, paramType = "body", dataType = "json string"),
//    })
//    @PostMapping(value = "/update-routes")
//    @ApiOperation(value = "添加或修改巡护路线", httpMethod = Constant.REQUEST_METHOD_POST)
//    public DataReturn updateRoutes(@RequestBody String cruiseRoutes) {
//        return DataReturn.ok(cameraMonitorService.updateRoutes(cruiseRoutes));
//    }
//
//    @ApiImplicitParams({
//            @ApiImplicitParam(name = "indexCode", value = "indexCode", required = true, paramType = "query", dataType = "String"),
//            @ApiImplicitParam(name = "cruiseIndex", value = "cruiseIndex", required = true, paramType = "query", dataType = "String"),
//    })
//    @PostMapping(value = "/deleteRoutes")
//    @ApiOperation(value = "删除巡航路线", httpMethod = Constant.REQUEST_METHOD_POST)
//    public DataReturn deleteRoutes(@RequestParam(value = "indexCode") String indexCode,
//                                   @RequestParam(value = "cruiseIndex") Integer cruiseIndex) {
//        return DataReturn.ok(cameraMonitorService.deleteRoutes(indexCode, cruiseIndex));
//    }
//
//    @ApiImplicitParams({
//            @ApiImplicitParam(name = "indexCode", value = "indexCode", required = true, paramType = "query", dataType = "String"),
//            @ApiImplicitParam(name = "monitoringType", value = "monitoringType", required = true, paramType = "query", dataType = "String"),
//            @ApiImplicitParam(name = "command", value = "command", required = true, paramType = "query", dataType = "String"),
//            @ApiImplicitParam(name = "cruiseIndex", value = "cruiseIndex", required = true, paramType = "query", dataType = "String"),
//    })
//    @PostMapping(value = "/controlRoutes")
//    @ApiOperation(value = "巡航控制 (command 开始巡航：START_CRUISE；停止巡航：STOP_CRUISE )", httpMethod = Constant.REQUEST_METHOD_POST)
//    public DataReturn controlRoutes(@RequestParam(value = "indexCode") String indexCode,
//                                    @RequestParam(value = "monitoringType") String monitoringType,
//                                    @RequestParam(value = "command") String command,
//                                    @RequestParam(value = "cruiseIndex") Integer cruiseIndex) {
//        return DataReturn.ok(cameraMonitorService.controlRoutes(indexCode, monitoringType, command, cruiseIndex));
//    }

    // ================================== 以下接口调用windows服务 ================================

    /**
     * 视频下载
     *
     * @param userId          用户id
     * @param cameraIndexCode 监控点编号
     * @param beginTime       开始时间
     * @param endTime         结束时间
     *
     * @return DataReturn Obj
     */
    @GetMapping(value = "/downloadVideo", produces = MediaType.APPLICATION_JSON_VALUE)
    @ApiImplicitParams({
            @ApiImplicitParam(name = "userId", value = "用户id", required = true, paramType = "query", dataType = "String"),
            @ApiImplicitParam(name = "cameraIndexCode", value = "监控点唯一标识", required = true, paramType = "query", dataType = "String"),
            @ApiImplicitParam(name = "beginTime", value = "开始时间，格式 yyyy-MM-dd HH:mm:ss", required = true, paramType = "query", dataType = "String"),
            @ApiImplicitParam(name = "endTime", value = "结束时间，格式 yyyy-MM-dd HH:mm:ss", required = true, paramType = "query", dataType = "String"),
            @ApiImplicitParam(name = "recordLocation", value = "录像存储位置（0-中心存储，1-设备存储）,默认中心存储", paramType = "query", dataType = "String"),
    })
    @ApiOperation(value = "视频下载", httpMethod = Constant.REQUEST_METHOD_GET)
    public DataReturn downloadVideo(@RequestParam String userId,
                                    @RequestParam String cameraIndexCode,
                                    @RequestParam String beginTime,
                                    @RequestParam String endTime,
                                    @RequestParam(value = "recordLocation", required = false) String recordLocation) {
        return cameraMonitorService.downloadVideo(userId, cameraIndexCode, beginTime, endTime, recordLocation);
    }

    @GetMapping(value = "/queryIsDownloadByCameraId", produces = MediaType.APPLICATION_JSON_VALUE)
    @ApiImplicitParams({
            @ApiImplicitParam(name = "userId", value = "用户id", required = true, paramType = "query", dataType = "String"),
            @ApiImplicitParam(name = "cameraIndexCode", value = "监控点唯一标识", required = true, paramType = "query", dataType = "String"),
    })
    @ApiOperation(value = "查询是否正在下载 0没有 1有", httpMethod = Constant.REQUEST_METHOD_GET)
    public DataReturn queryIsDownloadByCameraId(@RequestParam String userId, @RequestParam String cameraIndexCode) {
        return cameraMonitorService.queryIsDownloadByCameraId(userId, cameraIndexCode);
    }

    /**
     * 下载文件
     *
     * @param fileName 文件名称
     * @param response 输出流
     */
    @GetMapping(value = "/download")
    @ApiImplicitParams({
            @ApiImplicitParam(name = "fileName", value = "文件名称", required = true, paramType = "query", dataType = "String"),
    })
    @ApiOperation(value = "根据名称下载文件", httpMethod = Constant.REQUEST_METHOD_GET)
    public void download(@RequestParam(value = "fileName") String fileName, HttpServletResponse response) {
        cameraMonitorService.download(fileName, response);
    }

    /**
     * 删除文件
     *
     * @param fileName 文件名称
     *
     * @return DataReturn Obj
     */
    @GetMapping(value = "/delete")
    @ApiImplicitParams({
            @ApiImplicitParam(name = "fileName", value = "文件名称", required = true, paramType = "query", dataType = "String"),
    })
    @ApiOperation(value = "根据名称删除文件", httpMethod = Constant.REQUEST_METHOD_GET)
    public DataReturn delete(@RequestParam(value = "fileName") String fileName) {
        return cameraMonitorService.delete(fileName);
    }

    @GetMapping(value = "/subscribeEvent")
    @ApiOperation("订阅火情事件")
    public DataReturn subscribeEvent(String callbackUrl,int[] eventTypes) {
        String result=cameraMonitorService.subscribeEvent(callbackUrl,eventTypes);
        return DataReturn.ok(result);
    }

    @GetMapping(value = "/unSubscribeEvent")
    @ApiOperation("取消订阅火情事件")
    public DataReturn unSubscribeEvent(int[] eventTypes) {
        String result=cameraMonitorService.unSubscribeEvent(eventTypes);
        return DataReturn.ok(result);
    }

    @GetMapping(value = "/viewEvent")
    @ApiOperation("查询订阅火情事件")
    public DataReturn viewEvent() {
        String result=cameraMonitorService.viewEvent();
        return DataReturn.ok(result);
    }

}
